﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using AgencyEntityLib.BaseEntity;
using System.Web.UI.WebControls;
using System.Web.UI;
using Ecopsy.DataTier;

namespace Grishko.UI
{
    /// <summary>
    /// Дерево принимающее в качестве источника TreeEntity
    /// </summary>
    public class TreeControl : Control
    {
        public class TreeControlEventArgs : EventArgs
        {
            TreeEntitySingle _nd ;

            public TreeControlEventArgs(TreeEntitySingle nd)
            {
                _nd =nd;
            }
            public TreeEntitySingle ND
            {
                get { return _nd; }
            }
        }



        public delegate Control  _BuildNode(TreeControl tree,  TreeEntitySingle nd);
        public event _BuildNode BuildNode;

        protected  TreeDictionaryItem _DataSource   = null;
        public Unit _TabWidtch                      = new Unit("10px");
        public Unit _NodeWidtch                     = new Unit("250px");
        public string _CssNode                      = "TreeNode";
        public string  _CssSelectedNode             = string .Empty ;
        public bool _Collapse                       = true;
        public string _CollapseCssUp                = "CollapseCssUp";
        public string _CollapseCssDown              = "CollapseCssDown";


        /// <summary>
        /// Вызов BuildNodeEvent  - позволяет наследникам дерагть BuildNodeEvent
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        protected  Control Call_BuildNodeEvent(TreeControl tree, TreeEntitySingle nd)
        {
            if(null==BuildNode)
                         return null ;

            return BuildNode(tree, nd); 

        }

        public TreeControl()
        {

        }

        #region Property

         protected string GetRootId ()
         {
             return "Root_" + this.ID;
         }

        
   
        /// <summary>
        /// Источник 
        /// </summary>
        public virtual  TreeDictionaryItem DataSource { get { return _DataSource; } set { _DataSource = value; } }
        
        /// <summary>
        /// Величина отступов между узлами
        /// </summary>
        public Unit TabWidtch { get { return _TabWidtch; } set { _TabWidtch = value; } }
        
        /// <summary>
        /// Максимальная ширина ноды
        /// </summary>
        public Unit NodeWidtch { get { return _NodeWidtch; } set { _NodeWidtch = value; } }
        
        /// <summary>
        /// Нода CSS
        /// </summary>
        public string CssNode { get { return _CssNode; } set { _CssNode = value; } }
        
        /// <summary>
        /// Выделенная нода CSS
        /// </summary>
        public string CssSelectedNode { get { return _CssSelectedNode; } set { _CssSelectedNode = value; } }


        /// <summary>
        /// css кнопки развертки узлов
        /// </summary>
        public string CollapseCssUp { get { return _CollapseCssUp; } set { _CollapseCssUp = value; } }

        /// <summary>
        /// css кнопки развертки узлов
        /// </summary>
        public string CollapseCssDown { get { return _CollapseCssDown ; } set { _CollapseCssDown = value; } }



        /// <summary>
        /// В каком виде при загрузке (открыт закрыт)
        /// </summary>
        public bool TreeIsCollapse { get { return _Collapse; } set { _Collapse = value; } }

        #endregion

        protected virtual  void OnBefore_RenderControl(ref Panel Root) 
        { 
          
        }

        public override void DataBind()
        {

            base.DataBind();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (this.DesignMode)
            {
                writer.Write("Деревце");
                return;
            }

            // прорисовываем только если есть источник
            if (null == DataSource)            
                                return;                            
            if(bEnableRander)
                    MyRender(writer);

        }

        protected override void OnDataBinding(EventArgs e)
        {
            //base.OnDataBinding(e);
            bEnableRander=true ;
        }
        

        //Открыть закрыть отображение элемента
        private bool bEnableRander=false ;
        protected virtual void MyRender(HtmlTextWriter writer)
        {

            Func<TreeEntitySingle, int, Panel, bool, Panel> fBuild = delegate(TreeEntitySingle nd, int CurrentLevel, Panel CurrentPanel, bool isNode)
            {
                Table t = GetTable(CurrentLevel, isNode, nd);
                CurrentPanel.Controls.Add(t);
                return CurrentPanel;
            };

            Panel Root = new Panel() { ID = GetRootId() };
            NextNode((TreeEntitySingle)DataSource.First, Root, 1, true, fBuild);

            OnBefore_RenderControl(ref Root);
            
            Root.RenderControl(writer);

        }


        /// <summary>
        /// Генератор DivID
        /// </summary>
        /// <param name="nd"></param>
        /// <param name="CurrentLevel"></param>
        /// <returns></returns>
        private string GetDivID(TreeEntitySingle nd, int CurrentLevel)
        {
            if (null == nd)
                return string.Empty;

            return "dv_" + this.ID + CurrentLevel.ToString() + "___" + nd.ID;
        }


        private void NextNode(TreeEntitySingle nd,
                                Panel CurrentPanel,
                                int CurrentLevel,
                                bool isNode,
                                Func<TreeEntitySingle, int, Panel, bool, Panel> fBuild)
        {
            CurrentLevel++;
            //вставить в текущую панель - табличку  
            isNode = nd.ChildNodes.Count > 0;
            fBuild(nd, CurrentLevel, CurrentPanel, isNode);
            //матрешка панелей 
            if (nd.ChildNodes.Count > 0)
            {
                Panel p = new Panel() { ID = GetDivID(nd, CurrentLevel) };
                CurrentPanel.Controls.Add(p);
                CurrentPanel = p;
                CurrentPanel.Attributes.Add("isNode", "true");

                if (TreeIsCollapse)
                    CurrentPanel.Attributes.Add("style", "display: none"); 
            }

            nd.ChildNodes.Reset();
            foreach (TreeDictionaryItem i in nd.ChildNodes)
            {
                NextNode(i, CurrentPanel, CurrentLevel, isNode, fBuild);

            }


        }

        private Table GetTable(int TabCount, bool isNode, TreeEntitySingle nd)
        {
            Table res = new Table();
            TableRow rw = new TableRow() { CssClass = CssNode };
            for (int i = 0; i < TabCount + 1; i++)
            {
                TableCell cell = new TableCell() { Width = new Unit("10px"), Text = "&nbsp" };
                rw.Cells.Add(cell);                
            }

            if (isNode)
            {
                rw.Cells[TabCount - 2].ID = "ToggleNode_" + nd.ID+this.ID ;
                rw.Cells[TabCount - 2].CssClass = _CollapseCssUp   ;
                string sToggelNode="ToggelNode ('{0}','{1}','{2}','{3}');";
                string[] sToggelNode_Var = { rw.Cells[TabCount - 2].ID,GetDivID(nd, TabCount), _CollapseCssUp, _CollapseCssDown };
                rw.Cells[TabCount - 2].Attributes.Add("onclick", string .Format (sToggelNode ,sToggelNode_Var));
            }
            rw.Cells[TabCount - 1].Width = NodeWidtch;

            Control c = F_BuildNode(nd);
            if(null!=c)
                rw.Cells[TabCount - 1].Controls.Add(c);

            res.Rows.Add(rw);
            return res;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="nd"></param>
        /// <returns></returns>
        protected virtual Control F_BuildNode(TreeEntitySingle nd)
        {
            if (null != BuildNode)
                            return BuildNode(this,nd);

            LinkButton btn = new LinkButton();
            btn.CssClass = CssNode;
            btn.Text = (nd as TreeDictionaryItem).Name;
            return btn;
        }


        
    }
}
